package com.javaspeak.concurrency.nio.niolet;

import java.util.concurrent.Callable;

import org.apache.log4j.Logger;

import com.javaspeak.concurrency.nio.niolet.client.Client;
import com.javaspeak.concurrency.nio.niolet.client.ClientException;
import com.javaspeak.concurrency.nio.niolet.client.ClientImpl;


/**
 * @author John Dickerson
 */
public class ClientRequest implements Callable<CallStatusEnum>{

    public Logger logger = Logger.getLogger( ClientRequest.class );

    private long clientId;
    private String[] messages;
    private Client client;


    public ClientRequest( long clientId,
            String[] messages, String hostName, int port ){

        this.clientId = clientId;
        this.messages = messages;
        client = new ClientImpl( hostName, port );
    }

    public CallStatusEnum call() throws Exception {

        CallStatusEnum callStatusEnum;

        int connectCount = 0;

        try {

            Exception exception = null;

            while ( connectCount < 100 ){

                try {
                    client.open();
                    break;
                }
                catch( ClientException e ){

                    exception = e;

                    try {
                        Thread.sleep( 1000 );
                    }
                    catch( InterruptedException ee ){
                        // do nothing
                    }

                    connectCount++;
                }
            }

            if ( exception != null ){

                throw exception;
            }

            String response;

            for ( String message : messages ){

                response = client.doRequest( new ClientNioletMock( message ) );

                if ( ! response.equals( message.toUpperCase() ) ){

                    callStatusEnum =
                        CallStatusEnum.FAILED_NOT_CONVERTED_TO_UPPERCASE;

                    return callStatusEnum;
                }
            }

            callStatusEnum = CallStatusEnum.PASSED;

            logger.debug( "Client " + clientId + " : " +
                    callStatusEnum.getDescription() );

            return callStatusEnum;
        }
        catch( Throwable e ){

            callStatusEnum = CallStatusEnum.FAILED_EXCEPTION;

            logger.debug( "Client " + clientId + " : " +
                    callStatusEnum.getDescription() );

            return callStatusEnum;
        }
        finally {

            try {
                client.close();
            }
            catch( ClientException e ){
                // do nothing
            }
        }
    }
}
